package com.fbt.transfer.app.driver.socket;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.util.Log;
import cn.hutool.core.text.CharSequenceUtil;
import com.fbt.transfer.app.driver.BuildConfig;
import com.fbt.transfer.app.driver.service.FloatingWindowService;
import com.fbt.transfer.app.driver.util.NotificationUtils;
import com.fbt.transfer.app.driver.util.UserManager;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
import org.jetbrains.annotations.NotNull;

public class SocketManager {
    private static final String TAG = "SocketManager";
    /**
     * 替换为实际的 WebSocket 服务器地址
     */
    private static final String WS_URL_TEST = BuildConfig.DEV_SOCKET_URL;
    private static final String WS_URL_PRODUCTION = BuildConfig.PROD_SOCKET_URL;
    private String wsUrl;
    /**
     * 重连延迟时间（毫秒）
     */
    private static final int RECONNECT_DELAY = 10000;
    /**
     * 最大重连次数
     */
    private static final int MAX_RECONNECT_ATTEMPTS = 10;
    /**
     * 心跳间隔（毫秒）
     */
    private static final int HEARTBEAT_INTERVAL = 30000;
    private static final String HEARTBEAT_MESSAGE = "ping";
    private static final int CONNECT_TIMEOUT = 30000; // 连接超时时间
    private static final String WAKE_LOCK_TAG = "com.fbt.www.app.driver.socket:WebSocketWakeLock";
    private static final int MESSAGE_RATE_LIMIT = 100; // 消息发送频率限制（毫秒）
    private static final int MAX_QUEUE_SIZE = 1000; // 最大队列大小
    private static final int MESSAGE_EXPIRE_TIME = 30000; // 消息过期时间（30秒）
    private static final int HEARTBEAT_TIMEOUT = HEARTBEAT_INTERVAL * 2; // 心跳超时时间

    @SuppressLint("StaticFieldLeak")
    private static volatile SocketManager instance;
    private WebSocket webSocket = null;
    private OkHttpClient client;
    private final Context context;
    private final AtomicBoolean isConnecting = new AtomicBoolean(false);
    private final AtomicBoolean isConnected = new AtomicBoolean(false);
    private int reconnectAttempts = 0;
    private final Handler reconnectHandler = new Handler(Looper.getMainLooper());
    private final Handler heartbeatHandler = new Handler(Looper.getMainLooper());
    private Runnable reconnectRunnable = null;
    private Runnable heartbeatRunnable;
    private final UserManager userManager;
    private final PriorityBlockingQueue<MessageWrapper> messageQueue;
    private final ConnectivityManager connectivityManager;
    private PowerManager.WakeLock wakeLock;
    private boolean isBackground = false;
    private long lastMessageTime = 0;
    private long lastHeartbeatTime = 0;
    private final BroadcastReceiver networkReceiver;
    private final Handler mainHandler = new Handler(Looper.getMainLooper());

    public interface ConnectionStateListener {

        void onConnectionStateChanged(boolean isConnected);
    }

    private ConnectionStateListener connectionStateListener = null;

    public void setConnectionStateListener(ConnectionStateListener listener) {
        this.connectionStateListener = listener;
    }

    private void notifyConnectionStateChanged(boolean connected) {
        isConnected.set(connected);
        if (connectionStateListener != null) {
            mainHandler.post(() -> connectionStateListener.onConnectionStateChanged(connected));
        }
    }

    private SocketManager(Context context) {
        this.context = context.getApplicationContext();
        this.userManager = UserManager.getInstance(context);
        this.connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        this.messageQueue = new PriorityBlockingQueue<>(
            MAX_QUEUE_SIZE,
            (a, b) -> {
                if (a.priority != b.priority) {
                    return b.priority - a.priority;
                }
                return Long.compare(a.timestamp, b.timestamp);
            }
        );
        this.wsUrl = userManager.isTestEnvironment() ? WS_URL_TEST : WS_URL_PRODUCTION;
        this.networkReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
                    if (isNetworkAvailable()) {
                        if (!isConnected.get()) {
                            reconnect();
                        }
                    }
                }
            }
        };
        initWakeLock();
        initOkHttpClient();
        initHeartbeat();
        registerNetworkReceiver();
        startConnectionMonitor();
    }

    private void initWakeLock() {
        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG);
        wakeLock.setReferenceCounted(false);
    }

    private void acquireWakeLock() {
        if (wakeLock != null && !wakeLock.isHeld()) {
            wakeLock.acquire(24 * 60 * 60 * 1000L); // 24小时超时
        }
    }

    private void releaseWakeLock() {
        if (wakeLock != null && wakeLock.isHeld()) {
            wakeLock.release();
        }
    }

    public void setBackground(boolean isBackground) {
        this.isBackground = isBackground;
        Log.d(TAG, "Setting background state: " + isBackground);
        
        // 检查悬浮窗是否启用
        if (UserManager.getInstance(context).isFloatingWindowEnabled()) {
            if (isBackground) {
                Log.d(TAG, "Floating window is enabled and app is in background, starting service");
                // 检查服务是否已经在运行
                if (!isServiceRunning(FloatingWindowService.class)) {
                    // 延迟启动服务，避免重复启动
                    new Handler(Looper.getMainLooper()).postDelayed(() -> {
                        if (this.isBackground && !isServiceRunning(FloatingWindowService.class)) {
                            startFloatingWindowService();
                        }
                    }, 100); // 从500ms减少到100ms
                } else {
                    Log.d(TAG, "Floating window service already running");
                }
            } else {
                Log.d(TAG, "App returning to foreground, stopping service");
                stopFloatingWindowService();
            }
        } else {
            Log.d(TAG, "Floating window is disabled");
        }
    }

    private boolean isServiceRunning(Class<?> serviceClass) {
        android.app.ActivityManager manager = (android.app.ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        for (android.app.ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (serviceClass.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

    private void initHeartbeat() {
        heartbeatRunnable = new Runnable() {
            @Override
            public void run() {
                if (isConnected.get() && webSocket != null) {
                    try {
                        // 检查上次心跳时间
                        if (System.currentTimeMillis() - lastHeartbeatTime > HEARTBEAT_TIMEOUT) {
                            Log.w(TAG, "心跳间隔过长，重新连接");
                            attemptReconnect();
                            return;
                        }

                        webSocket.send(HEARTBEAT_MESSAGE);
                        lastHeartbeatTime = System.currentTimeMillis();
                        heartbeatHandler.postDelayed(this, HEARTBEAT_INTERVAL);
                    } catch (Exception e) {
                        Log.e(TAG, "发送心跳失败", e);
                        attemptReconnect();
                    }
                }
            }
        };
    }

    public static SocketManager getInstance(Context context) {
        if (instance == null) {
            synchronized (SocketManager.class) {
                if (instance == null) {
                    instance = new SocketManager(context);
                }
            }
        }
        return instance;
    }

    private void initOkHttpClient() {
        client = new OkHttpClient.Builder()
                .readTimeout(0, TimeUnit.MILLISECONDS)
                .connectTimeout(CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
                .writeTimeout(CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
                .retryOnConnectionFailure(true)
                .pingInterval(15, TimeUnit.SECONDS) // 添加ping间隔
                .build();
    }

    private boolean isNetworkAvailable() {
        if (connectivityManager == null) {
            return false;
        }
        NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
        return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    }

    public synchronized void connect() {
        // 1. 检查网络状态
        if (!isNetworkAvailable()) {
            Log.d(TAG, "网络不可用，不建立WebSocket连接");
            return;
        }

        // 2. 检查token
        String token = userManager.getToken();
        if (CharSequenceUtil.isBlank(token)) {
            Log.d(TAG, "Token为空，不建立WebSocket连接");
            return;
        }

        // 3. 检查连接状态
        if (isConnecting.get() || isConnected.get()) {
            Log.d(TAG, "WebSocket已经在连接中或已连接，跳过重复连接");
            return;
        }

        // 4. 清理旧连接
        if (webSocket != null) {
            Log.d(TAG, "断开旧的WebSocket连接");
            webSocket.cancel();
            webSocket.close(1000, "重新连接");
            webSocket = null;
        }

        isConnecting.set(true);
        isConnected.set(false);

        // 5. 创建新连接
        Request request = new Request.Builder()
            .url(wsUrl)
            .header("x-access-token",  token)
            .header("Upgrade", "websocket")
            .header("Connection", "Upgrade")
            .build();

        // 添加连接超时处理
        Handler timeoutHandler = new Handler(Looper.getMainLooper());
        Runnable timeoutRunnable = () -> {
            if (isConnecting.get()) {
                Log.e(TAG, "连接超时");
                isConnecting.set(false);
                attemptReconnect();
            }
        };
        timeoutHandler.postDelayed(timeoutRunnable, CONNECT_TIMEOUT);

        WebSocketListener webSocketListener = new WebSocketListener() {
            @Override
            public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) {
                timeoutHandler.removeCallbacks(timeoutRunnable);
                Log.d(TAG, "WebSocket连接成功");
                isConnecting.set(false);
                notifyConnectionStateChanged(true);
                reconnectAttempts = 0;
                heartbeatHandler.post(heartbeatRunnable);
                processMessageQueue();
                
                // 如果是后台状态，保持WakeLock
                if (isBackground) {
                    acquireWakeLock();
                }
            }

            @Override
            public void onMessage(@NotNull WebSocket webSocket, String text) {
                Log.d(TAG, "收到消息: " + text);
                if (!HEARTBEAT_MESSAGE.equals(text)) {
                    handleMessage(text);
                }
            }

            @Override
            public void onMessage(@NotNull WebSocket webSocket, ByteString bytes) {
                Log.d(TAG, "收到二进制消息");
                handleMessage(bytes.utf8());
            }

            @Override
            public void onClosing(@NotNull WebSocket webSocket, int code, String reason) {
                timeoutHandler.removeCallbacks(timeoutRunnable);
                Log.d(TAG, "WebSocket正在关闭: " + reason);
                isConnecting.set(false);
                notifyConnectionStateChanged(false);
                stopHeartbeat();
            }

            @Override
            public void onClosed(@NotNull WebSocket webSocket, int code, String reason) {
                timeoutHandler.removeCallbacks(timeoutRunnable);
                Log.d(TAG, "WebSocket已关闭: " + reason);
                isConnecting.set(false);
                notifyConnectionStateChanged(false);
                stopHeartbeat();
                attemptReconnect();
            }

            @Override
            public void onFailure(@NotNull WebSocket webSocket, Throwable t, Response response) {
                timeoutHandler.removeCallbacks(timeoutRunnable);
                Log.e(TAG, "WebSocket连接失败", t);
                isConnecting.set(false);
                notifyConnectionStateChanged(false);
                stopHeartbeat();
                attemptReconnect();
            }
        };

        webSocket = client.newWebSocket(request, webSocketListener);
    }

    private void stopHeartbeat() {
        if (heartbeatHandler != null && heartbeatRunnable != null) {
            heartbeatHandler.removeCallbacks(heartbeatRunnable);
        }
    }

    private void processMessageQueue() {
        if (!isConnected.get() || webSocket == null) {
            return;
        }

        MessageWrapper messageWrapper;
        while ((messageWrapper = messageQueue.poll()) != null) {
            try {
                // 检查消息是否过期
                if (System.currentTimeMillis() - messageWrapper.timestamp > MESSAGE_EXPIRE_TIME) {
                    Log.w(TAG, "消息已过期，丢弃: " + messageWrapper.message);
                    continue;
                }

                // 检查消息发送频率限制
                long currentTime = System.currentTimeMillis();
                if (currentTime - lastMessageTime < MESSAGE_RATE_LIMIT) {
                    try {
                        Thread.sleep(MESSAGE_RATE_LIMIT - (currentTime - lastMessageTime));
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }

                webSocket.send(messageWrapper.message);
                lastMessageTime = System.currentTimeMillis();
            } catch (Exception e) {
                Log.e(TAG, "发送消息失败", e);
                if (messageWrapper.canRetry()) {
                    messageWrapper.incrementRetryCount();
                    messageQueue.offer(messageWrapper);
                }
                break;
            }
        }
    }

    public void sendMessage(String message, int priority) {
        if (CharSequenceUtil.isBlank(message)) {
            return;
        }

        // 检查队列大小
        if (messageQueue.size() >= MAX_QUEUE_SIZE) {
            Log.e(TAG, "消息队列已满，丢弃消息");
            return;
        }

        MessageWrapper messageWrapper = new MessageWrapper(message, priority);
        if (isConnected.get() && webSocket != null) {
            try {
                webSocket.send(message);
                lastMessageTime = System.currentTimeMillis();
            } catch (Exception e) {
                Log.e(TAG, "发送消息失败", e);
                messageQueue.offer(messageWrapper);
            }
        } else {
            messageQueue.offer(messageWrapper);
        }
    }

    private void attemptReconnect() {
        // 1. 检查token
        String token = userManager.getToken();
        if (CharSequenceUtil.isBlank(token)) {
            Log.d(TAG, "Token为空，停止重连");
            return;
        }

        // 2. 检查网络状态
        if (!isNetworkAvailable()) {
            Log.d(TAG, "网络不可用，停止重连");
            return;
        }

        // 3. 检查重连次数
        if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
            Log.e(TAG, "达到最大重连次数，停止重连");
            return;
        }

        // 4. 检查连接状态
        if (isConnected.get()) {
            Log.d(TAG, "已经连接，不需要重连");
            return;
        }

        reconnectAttempts++;
        Log.d(TAG, "尝试重连，第 " + reconnectAttempts + " 次");

        // 5. 取消之前的重连任务
        if (reconnectRunnable != null) {
            reconnectHandler.removeCallbacks(reconnectRunnable);
        }

        // 6. 使用指数退避算法
        long delay = RECONNECT_DELAY * (long) Math.pow(2, reconnectAttempts - 1);
        delay = Math.min(delay, 300000); // 最大延迟5分钟

        // 7. 创建新的重连任务
        reconnectRunnable = () -> {
            if (!isConnected.get() && !CharSequenceUtil.isBlank(userManager.getToken())) {
                connect();
            }
        };

        reconnectHandler.postDelayed(reconnectRunnable, delay);
    }

    private void handleMessage(String messageBody) {
        if (CharSequenceUtil.isBlank(messageBody)) {
            return;
        }
        mainHandler.post(() -> NotificationUtils.showNotification(context, messageBody));
    }

    public synchronized void disconnect() {
        // 1. 停止心跳
        stopHeartbeat();
        
        // 2. 关闭WebSocket连接
        if (webSocket != null) {
            webSocket.cancel();
            webSocket.close(1000, "用户退出登录");
            webSocket = null;
        }
        
        // 3. 重置状态
        isConnecting.set(false);
        isConnected.set(false);
        reconnectAttempts = 0;
        
        // 4. 清理重连任务
        if (reconnectRunnable != null) {
            reconnectHandler.removeCallbacks(reconnectRunnable);
            reconnectRunnable = null;
        }
        
        // 5. 清理消息队列
        messageQueue.clear();
        
        // 6. 释放WakeLock
        releaseWakeLock();
        
        // 7. 注销网络监听器
        unregisterNetworkReceiver();
        
        // 8. 通知状态变化
        notifyConnectionStateChanged(false);
    }

    public boolean isConnected() {
        return isConnected.get();
    }

    public void checkLoginStatus() {
        if (!userManager.isLoggedIn()) {
            Log.d(TAG, "检测到用户未登录，清除本地数据");
            userManager.clearUserInfo();
            disconnect();
        }
    }

    public void reconnect() {
        if (isConnected.get()) {
            return;
        }
        reconnectAttempts = 0; // 重置重连次数
        connect();
    }

    public void clearMessageQueue() {
        messageQueue.clear();
    }

    private void registerNetworkReceiver() {
        try {
            IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
            context.registerReceiver(networkReceiver, filter);
        } catch (Exception e) {
            Log.e(TAG, "注册网络监听器失败", e);
        }
    }

    private void unregisterNetworkReceiver() {
        try {
            context.unregisterReceiver(networkReceiver);
        } catch (Exception e) {
            Log.e(TAG, "注销网络监听器失败", e);
        }
    }

    private void startConnectionMonitor() {
        mainHandler.postDelayed(() -> {
            if (isConnected.get() && webSocket != null) {
                if (System.currentTimeMillis() - lastHeartbeatTime > HEARTBEAT_TIMEOUT) {
                    Log.e(TAG, "心跳超时，尝试重连");
                    attemptReconnect();
                }
            }
            // 继续监控
            startConnectionMonitor();
        }, HEARTBEAT_INTERVAL);
    }

    private void startFloatingWindowService() {
        try {
            Intent intent = new Intent(context, FloatingWindowService.class);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(intent);
            } else {
                context.startService(intent);
            }
            Log.d(TAG, "Floating window service started");
        } catch (Exception e) {
            Log.e(TAG, "Error starting floating window service: " + e.getMessage());
        }
    }

    private void stopFloatingWindowService() {
        try {
            Intent intent = new Intent(context, FloatingWindowService.class);
            context.stopService(intent);
            Log.d(TAG, "Floating window service stopped");
        } catch (Exception e) {
            Log.e(TAG, "Error stopping floating window service: " + e.getMessage());
        }
    }

    public boolean isBackground() {
        return isBackground;
    }
} 
